/*---------------------------------------------------------
 * Arquivo: matriz_utils.c - implementação de funções 
 * de manipulação de matrizes do tipo float e mycomplex
 * Programa: parallel fft-2d
 * Versão: 0.5.1
 *---------------------------------------------------------
 * */

#include "matriz_utils.h"



/**
 * @brief Aloca memória para uma matriz de ponteiros do tipo float 
 * @param m Número de linhas da matriz
 * @param n Número de colunas da matriz 
 * @param v Matriz de ponteiros a ser liberada
 * @author LidianyCS
 */
float **alocar_matriz (int m, int n)
{
  float **v;  /* ponteiro para a matriz */
  int   i;    /* variavel auxiliar      */
  if (m < 1 || n < 1) { /* verifica parametros recebidos */
     printf ("** Erro: Parametro invalido **\n");
     return (NULL);
     }
  /* aloca as linhas da matriz */
  v = (float **) calloc (m, sizeof(float *));
  if (v == NULL) {
     printf ("** Erro: Memoria Insuficiente **");
     return (NULL);
     }
  /* aloca as colunas da matriz */
  for ( i = 0; i < m; i++ ) {
      v[i] = (float*) calloc (n, sizeof(float));
      if (v[i] == NULL) {
         printf ("** Erro: Memoria Insuficiente **");
         return (NULL);
         }
      }
  return (v); /* retorna o ponteiro para a matriz */
}


/**
 * @brief Libera a memória alocada para uma matriz de ponteiros do tipo float 
 * @param m Número de linhas da matriz
 * @param n Número de colunas da matriz 
 * @param v Matriz de ponteiros a ser liberada
 * @author LidianyCS
 */
float **liberar_matriz(int m, int n, float **v)
{
  int  i;  /* variavel auxiliar */
  if (v == NULL) return (NULL);
  if (m < 1 || n < 1) {  /* verifica parametros recebidos */
     printf ("** Erro: Parametro invalido **\n");
     return (v);
     }
  for (i=0; i<m; i++) free (v[i]); /* libera as linhas da matriz */
  free (v);      /* libera a matriz */
  return (NULL); /* retorna um ponteiro nulo */
}


/**
 * @brief Lê algumas linhas da matriz contida no arquivo e retorna uma matriz de floats
 * @param l Total de linhas da matriz
 * @param c Total de colunas da matriz 
 * @param ind_relat Índice a partir do qual a matriz será lida, deve ser maior que zero
 * @param qtde_linhas Total de linhas da matriz do arquivo a serem lidas
 * @param nome_arquivo Nome do arquivo a ser lido
 * @author LidianyCS
 */
float **ler_linhas_arquivo(int l, int c, int ind_relat, int qtde_linhas, char *nome_arquivo){
	FILE *arquivo;
	
	float **matriz;
	
	matriz = alocar_matriz(qtde_linhas, c);
	
	arquivo = fopen(nome_arquivo,"rb");
	
	if(arquivo == NULL)
      {
        printf("Erro: não foi possível abrir o arquivo para leitura");
        exit(1);
      }        
	/*
	 * posiciona o cursor de acordo com o número de colunas e com 
	 * o indice relativo da matriz, dessa forma a matriz não é lida por 
	 * completo, apenas uma parte dela
	*/
	if(ind_relat > 0){
		fseek(arquivo, (ind_relat * c) * ( sizeof(float) ), SEEK_SET);
		
	}else{
		printf("Erro: o índice de leitura da matriz deve ser maior que 0.");
		exit(1);
	}
	
	int lin, col;
	 for(lin  = 0; lin<qtde_linhas; lin++){
		 for(col = 0; col<c; col++){
			 fread(&matriz[lin][col], sizeof(float), 1, arquivo); 			 
		 }
	 }	 
	 fclose(arquivo);
     return matriz;
} 


/**
 * @brief Lê o arquivo contendo uma matriz de floats e retorna a matriz
 * @param l Número de linhas da matriz
 * @param c Número de colunas da matriz 
 * @param nome_arquivo Nome do arquivo a ser lido
 * @author LidianyCS
 */
float **ler_arquivo(int l, int c, char *nome_arquivo){
	FILE *arquivo;
	
	float **matriz;
	
	matriz = alocar_matriz(l, c);
	
	arquivo = fopen(nome_arquivo,"rb");
	if(arquivo == NULL)
      {
        printf("Erro: não foi possível abrir o arquivo para leitura");
        exit(1);
      }        
	 int lin, col;
	 for(lin  = 0; lin<l; lin++){
		 for(col = 0; col<c; col++){
			 fread(&matriz[lin][col], sizeof(float), 1, arquivo); 			 
		 }
	 }	
		        
     fclose(arquivo);
     return matriz;
} 

/**
 * @brief Imprime o conteúdo de uma matriz de ponteiros do tipo float 
 * @param m Número de linhas da matriz
 * @param n Número de colunas da matriz
 * @param mat Matriz de ponteiros do tipo float
 * @author LidianyCS
 * */

void imprimir_matriz (int m, int n, float **mat)
{
      int lin, col;     
     for(lin  = 0; lin<m; lin++){
		 for(col = 0; col<n; col++){
			 			 
			 printf("mat[%d][%d] = %f\n", lin, col,
             mat[lin][col]);             		 
		 }
	 }
 }

/**
 * 
 * @brief Cria um arquivo com uma matriz de floats para teste 
 * @param l Número de linhas da matriz a ser criada
 * @param c Número de colunas da matriz a ser criada
 * @param nome_arquivo String com o nome do arquivo a ser criado
 *   
 * */
void criar_arquivo_teste(int l, int c, char *nome_arquivo){
	FILE *arquivo;	
	float **matriz;
	int lin, col;
    float x = 0.1;    

	matriz = alocar_matriz(l, c);
	
	arquivo = fopen(nome_arquivo,"w+b");
	if(arquivo == NULL)
      {
        printf("Erro ao abrir arquivo para leitura");
        exit(1);
      }        
	 for(lin  = 0; lin<l; lin++){
		 for(col = 0; col<c; col++){
			 matriz[lin][col] = x;			 
             x++;
             x = x*1.2; 			 
		 }
	 }
	
	 for(lin  = 0; lin<l; lin++){
		 for(col = 0; col<c; col++){
			 fwrite(&matriz[lin][col], sizeof(float), 1, arquivo); 			 
		 }
	 }            
     fclose(arquivo);
}

/**
 * @brief Função principal do arquivo, usada para testes
 * 
 * */
 
int main (void)
{
	
	int   l, c;   // total de linhas e colunas da matriz 
            l = 32;
            c = 32;
            
    int qtde_linhas = 4; //numero de linhas para testar leitura parcial 
    int ind_rel = 2; //indice relativo pra testar a leitura parcial 
    float **mat;  // matriz float a ser criada e lida
    char *nome_arquivo = "fft_teste.dat";
	criar_arquivo_teste(l, c, nome_arquivo); //cria o arquivo de teste
	printf("Arquivo de teste criado com sucesso \n");

 ///TESTAR MÉTODOS DO TIPO FLOAT
 
  
  printf("Testando metodos FLOAT\n");
  
  
  //lê somente parte do arquivo 
  //printf("Ler %d linha(s) da matriz, a partir da %d linha \n", qtde_linhas, ind_rel);
 // mat = ler_linhas_arquivo(l, c, ind_rel, qtde_linhas, nome_arquivo); 
  
  printf("Ler %d linha(s) da matriz, a partir da %d linha \n", l, c);
  mat = ler_arquivo(l, c, nome_arquivo);
 
		//INVERTER MATRIZ
 
  imprimir_matriz(4, c, mat);           
  mat = liberar_matriz(4, c, mat);
  printf("Metodos float ok!\n");
  printf("Matriz de float liberada!\n");  
  
  return 0;
}
*/

